// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: donggu

#include <experimental/filesystem>

#include <doctest.h>

#include "coin/proto/symbology.pb.h"
#include "coin2/exchange/base/market/enums.h"
#include "coin2/exchange/base/market/market_exchange_api.h"
#include "coin2/exchange/base/symbology/util.h"
#include "coin2/exchange/di/constant.h"

DOCTEST_TEST_CASE("product info") {
  coin2::exchange::di::ConstantInjectionBuilder b;
  coin2::exchange::di::ConstantInjection ci(b);

  DOCTEST_SUBCASE("Futures.Okex.v5") {
    const auto& pis = ci.GetProductInfo(
        {coin2::exchange::base::market::MarketType::Futures,
         coin2::exchange::base::market::ExchangeType::Okex,
         "v5"});
    {
      const auto& pi = pis.GetProductInfo("BTC-USD.QUARTER");
      DOCTEST_CHECK(pi.is_inverse() == true);
      DOCTEST_CHECK(pi.contract_value() == 100);
      DOCTEST_CHECK(pi.base() == "BTC");
      DOCTEST_CHECK(pi.quote() == "USD");
      DOCTEST_CHECK(pi.symbol() == "BTC-USD.QUARTER");
      DOCTEST_CHECK(pi.native_base() == "BTC");
      DOCTEST_CHECK(pi.native_quote() == "USD");
      DOCTEST_CHECK(pi.native_symbol().substr(0, 8) == "BTC-USD-");  // BTC-USD-200626
    }

    {
      const auto& pi = pis.GetProductInfo("BCHN-USD.QUARTER");
      DOCTEST_CHECK(pi.is_inverse() == true);
      DOCTEST_CHECK(pi.contract_value() == 10);
      DOCTEST_CHECK(pi.base() == "BCHN");
      DOCTEST_CHECK(pi.quote() == "USD");
      DOCTEST_CHECK(pi.symbol() == "BCHN-USD.QUARTER");
      DOCTEST_CHECK(pi.native_base() == "BCH");
      DOCTEST_CHECK(pi.native_quote() == "USD");
      DOCTEST_CHECK(pi.native_symbol().substr(0, 8) == "BCH-USD-");  // BCH-USD-200626
    }

    {
      const auto& pi = pis.GetProductInfo("BTC-USDT.QUARTER");
      DOCTEST_CHECK(pi.is_inverse() == false);
      DOCTEST_CHECK(pi.contract_value() == 0.01);
      DOCTEST_CHECK(pi.base() == "BTC");
      DOCTEST_CHECK(pi.quote() == "USDT");
      DOCTEST_CHECK(pi.symbol() == "BTC-USDT.QUARTER");
      DOCTEST_CHECK(pi.native_base() == "BTC");
      DOCTEST_CHECK(pi.native_quote() == "USDT");
      DOCTEST_CHECK(pi.native_symbol().substr(0, 9) == "BTC-USDT-");  // BTC-USD-200626
    }
  }
  DOCTEST_SUBCASE("Spot.Okex.v5") {
    const auto& pis = ci.GetProductInfo(
        {coin2::exchange::base::market::MarketType::Spot,
         coin2::exchange::base::market::ExchangeType::Okex,
         "v5"});
    {
      const auto& pi = pis.GetProductInfo("BTC-USDC");
      DOCTEST_CHECK(pi.is_inverse() == false);
      DOCTEST_CHECK(pi.contract_value() == 1);
      DOCTEST_CHECK(pi.base() == "BTC");
      DOCTEST_CHECK(pi.quote() == "USDC");
      DOCTEST_CHECK(pi.symbol() == "BTC-USDC");
      DOCTEST_CHECK(pi.native_base() == "BTC");
      DOCTEST_CHECK(pi.native_quote() == "USDC");
      DOCTEST_CHECK(pi.native_symbol() == "BTC-USDC");
    }

    DOCTEST_CHECK_FALSE(pis.HasNativeProduct("BTC-USD"));
  }
  DOCTEST_SUBCASE("Futures.Okex.v3-swap") {
    const auto& pis = ci.GetProductInfo(
        {coin2::exchange::base::market::MarketType::Futures,
         coin2::exchange::base::market::ExchangeType::Okex,
         "v5-swap"});
    {
      auto pi = pis.GetProductInfo("BTC-USD.PERPETUAL");
      DOCTEST_CHECK(pi.is_inverse() == true);
      DOCTEST_CHECK(pi.contract_value() == 100);
      DOCTEST_CHECK(pi.base() == "BTC");
      DOCTEST_CHECK(pi.quote() == "USD");
      DOCTEST_CHECK(pi.symbol() == "BTC-USD.PERPETUAL");
      DOCTEST_CHECK(pi.native_base() == "BTC");
      DOCTEST_CHECK(pi.native_quote() == "USD");
      DOCTEST_CHECK(pi.native_symbol() == "BTC-USD-SWAP");
    }
  }

  /* ---------------------------------- huobi --------------------------------- */

  DOCTEST_SUBCASE("Futures.Huobi.v1") {
    const auto& pis = ci.GetProductInfo(
        {coin2::exchange::base::market::MarketType::Futures,
         coin2::exchange::base::market::ExchangeType::Huobi,
         "v1"});

    const auto& pi = pis.GetProductInfo("BTC-USD.QUARTER");
    DOCTEST_CHECK(pi.is_inverse() == true);
    DOCTEST_CHECK(pi.contract_value() == 100);
    DOCTEST_CHECK(pi.base() == "BTC");
    DOCTEST_CHECK(pi.quote() == "USD");
    DOCTEST_CHECK(pi.symbol() == "BTC-USD.QUARTER");
    DOCTEST_CHECK(pi.native_base() == "BTC");
    DOCTEST_CHECK(pi.native_quote() == "USD");
    DOCTEST_CHECK(pi.native_symbol().substr(0, 4) == "BTC2");  // BTC200626
  }
  DOCTEST_SUBCASE("Spot.Huobi.v1") {
    const auto& pis = ci.GetProductInfo(
        {coin2::exchange::base::market::MarketType::Spot,
         coin2::exchange::base::market::ExchangeType::Huobi,
         "v1"});
    {
      const auto& pi = pis.GetProductInfo("BTC-USDT");
      DOCTEST_CHECK(pi.is_inverse() == false);
      DOCTEST_CHECK(pi.contract_value() == 1);
      DOCTEST_CHECK(pi.price_ticksize()[0].value() == doctest::Approx(1e-2));
      DOCTEST_CHECK(pi.qty_ticksize()[0].value() == doctest::Approx(1e-6));
      DOCTEST_CHECK(pi.base() == "BTC");
      DOCTEST_CHECK(pi.quote() == "USDT");
      DOCTEST_CHECK(pi.symbol() == "BTC-USDT");
      DOCTEST_CHECK(pi.native_base() == "btc");
      DOCTEST_CHECK(pi.native_quote() == "usdt");
      DOCTEST_CHECK(pi.native_symbol() == "btcusdt");
    }

    DOCTEST_CHECK_FALSE(pis.HasNativeProduct("BTC-USD"));
  }

  DOCTEST_SUBCASE("Futures.Huobi.v1-swap") {
    const auto& pis = ci.GetProductInfo(
        {coin2::exchange::base::market::MarketType::Futures,
         coin2::exchange::base::market::ExchangeType::Huobi,
         "v1-swap"});
    {
      const auto& pi = pis.GetProductInfo("BTC-USD.PERPETUAL");
      DOCTEST_CHECK(pi.is_inverse() == true);
      DOCTEST_CHECK(pi.contract_value() == 100);
      DOCTEST_CHECK(pi.base() == "BTC");
      DOCTEST_CHECK(pi.quote() == "USD");
      DOCTEST_CHECK(pi.symbol() == "BTC-USD.PERPETUAL");
      DOCTEST_CHECK(pi.native_base() == "BTC");
      DOCTEST_CHECK(pi.native_quote() == "USD");
      DOCTEST_CHECK(pi.native_symbol() == "BTC-USD");
    }
  }

  DOCTEST_SUBCASE("Futures.Binance.v1") {
    const auto& pis = ci.GetProductInfo(
        {coin2::exchange::base::market::MarketType::Futures,
         coin2::exchange::base::market::ExchangeType::Binance,
         "v1"});

    {
      const auto& pi = pis.GetProductInfo("BCHN-USDT.PERPETUAL");
      DOCTEST_CHECK(pi.is_inverse() == false);
      DOCTEST_CHECK(pi.contract_value() == 1);
      DOCTEST_CHECK(pi.base() == "BCHN");
      DOCTEST_CHECK(pi.quote() == "USDT");
      DOCTEST_CHECK(pi.symbol() == "BCHN-USDT.PERPETUAL");
      DOCTEST_CHECK(pi.native_base() == "BCH");
      DOCTEST_CHECK(pi.native_quote() == "USDT");
      DOCTEST_CHECK(pi.native_symbol() == "BCHUSDT");
    }
  }
}
